import { WebSocketServer, WebSocket } from 'ws';
import { parse as parseUrl } from 'url';
import http from 'http';

// 创建HTTP服务器
const server = http.createServer((req, res) => {
  // 设置CORS头
  res.setHeader('Access-Control-Allow-Origin', '*');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
  
  // 处理预检请求
  if (req.method === 'OPTIONS') {
    res.writeHead(204);
    res.end();
    return;
  }
  
  res.writeHead(404);
  res.end();
});

// 创建WebSocket服务器，使用HTTP服务器
const wss = new WebSocketServer({ server });

// 存储房间和连接
const rooms = new Map();
const streamers = new Map(); // 存储直播发起者
const checkInData = new Map(); // 存储签到数据 {roomId: {count: 0, users: new Set()}}
const voteData = new Map(); // 存储投票数据 {roomId: {isActive: false, question: '', options: [], results: {}, totalVotes: 0, voters: new Set()}}

console.log('WebRTC信令服务器运行在端口 9000');

wss.on('connection', (ws, req) => {
  console.log('新的WebSocket连接');
  
  // 从URL中提取房间ID
  const pathname = parseUrl(req.url).pathname;
  const roomMatch = pathname.match(/\/room\/(.+)/);
  const roomId = roomMatch ? roomMatch[1] : null;
  
  let clientId = generateClientId();
  let isStreamer = false;
  
  if (!roomId) {
    ws.close(1008, '无效的房间ID');
    return;
  }
  
  console.log(`客户端 ${clientId} 尝试连接房间 ${roomId}`);
  
  ws.on('message', (message) => {
    try {
      const data = JSON.parse(message);
      console.log('收到消息:', data.type, '来自:', clientId);
      
      switch (data.type) {
        case 'start-streaming':
          handleStartStreaming(ws, roomId, clientId);
          break;
        case 'viewer-join':
          handleViewerJoin(ws, roomId, clientId);
          break;
        case 'offer':
          handleOffer(data, roomId, clientId);
          break;
        case 'answer':
          handleAnswer(data, roomId, clientId);
          break;
        case 'ice-candidate':
          handleIceCandidate(data, roomId, clientId);
          break;
        case 'danmaku':
          handleDanmaku(data, roomId, clientId);
          break;
        case 'check-in':
          handleCheckIn(ws, data, roomId, clientId);
          break;
        case 'get-checkin-stats':
          handleGetCheckInStats(ws, roomId, clientId);
          break;
        case 'reset-checkin':
          handleResetCheckIn(roomId, clientId);
          break;
        case 'message':
          handleChatMessage(data, roomId, clientId);
          break;
        case 'start-vote':
          handleStartVote(ws, data, roomId, clientId);
          break;
        case 'end-vote':
          handleEndVote(ws, roomId, clientId);
          break;
        case 'reset-vote':
          handleResetVote(roomId, clientId);
          break;
        case 'vote':
          handleVote(ws, data, roomId, clientId);
          break;
        case 'get-vote-stats':
          handleGetVoteStats(ws, roomId, clientId);
          break;
        default:
          console.log('未知消息类型:', data.type);
      }
    } catch (error) {
      console.error('解析消息失败:', error);
    }
  });
  
  ws.on('close', () => {
    console.log(`WebSocket连接关闭: ${clientId}`);
    handleDisconnection(roomId, clientId, isStreamer);
  });
  
  ws.on('error', (error) => {
    console.error('WebSocket错误:', error);
  });
  
  // 开始直播处理
  function handleStartStreaming(ws, roomId, clientId) {
    if (streamers.has(roomId)) {
      ws.send(JSON.stringify({
        type: 'error',
        message: '房间内已有直播进行中'
      }));
      return;
    }
    
    streamers.set(roomId, { ws, clientId });
    isStreamer = true;
    
    if (!rooms.has(roomId)) {
      rooms.set(roomId, new Map());
    }
    
    const room = rooms.get(roomId);
    room.set(clientId, { ws, type: 'streamer' });
    
    console.log(`直播开始: 房间 ${roomId}, 主播 ${clientId}`);
    
    ws.send(JSON.stringify({
      type: 'streaming-started',
      roomId,
      clientId
    }));
  }
  
  // 观众加入处理
  function handleViewerJoin(ws, roomId, clientId) {
    if (!rooms.has(roomId)) {
      rooms.set(roomId, new Map());
    }
    
    const room = rooms.get(roomId);
    room.set(clientId, { ws, type: 'viewer' });
    
    console.log(`观众加入: 房间 ${roomId}, 观众 ${clientId}`);
    
    // 如果有直播进行中，通知主播有新观众
    if (streamers.has(roomId)) {
      const streamer = streamers.get(roomId);
      if (streamer.ws.readyState === WebSocket.OPEN) {
        streamer.ws.send(JSON.stringify({
          type: 'viewer-join',
          from: clientId,
          roomId
        }));
      }
    } else {
      // 没有直播，通知观众
      ws.send(JSON.stringify({
        type: 'no-stream',
        message: '当前房间没有直播'
      }));
    }
  }
  
  // 处理offer
  function handleOffer(data, roomId, clientId) {
    const targetId = data.to;
    if (rooms.has(roomId)) {
      const room = rooms.get(roomId);
      const target = room.get(targetId);
      
      if (target && target.ws.readyState === WebSocket.OPEN) {
        target.ws.send(JSON.stringify({
          type: 'offer',
          data: data.data,
          from: clientId
        }));
        console.log(`转发offer: ${clientId} -> ${targetId}`);
      } else {
        console.error(`无法转发offer: 目标 ${targetId} 不存在或连接已关闭`);
      }
    }
  }
  
  // 处理answer
  function handleAnswer(data, roomId, clientId) {
    const targetId = data.to;
    if (rooms.has(roomId)) {
      const room = rooms.get(roomId);
      const target = room.get(targetId);
      
      if (target && target.ws.readyState === WebSocket.OPEN) {
        target.ws.send(JSON.stringify({
          type: 'answer',
          data: data.data,
          from: clientId
        }));
        console.log(`转发answer: ${clientId} -> ${targetId}`);
      } else {
        console.error(`无法转发answer: 目标 ${targetId} 不存在或连接已关闭`);
      }
    }
  }
  
  // 处理ICE候选
  function handleIceCandidate(data, roomId, clientId) {
    const targetId = data.to;
    
    if (targetId) {
      // 有指定目标，直接转发
      if (rooms.has(roomId)) {
        const room = rooms.get(roomId);
        const target = room.get(targetId);
        
        if (target && target.ws.readyState === WebSocket.OPEN) {
          target.ws.send(JSON.stringify({
            type: 'ice-candidate',
            data: data.data,
            from: clientId
          }));
          console.log(`转发ICE候选: ${clientId} -> ${targetId}`);
        } else {
          console.error(`无法转发ICE候选: 目标 ${targetId} 不存在或连接已关闭`);
        }
      }
    } else {
      // 没有指定目标，转发给主播
      if (streamers.has(roomId)) {
        const streamer = streamers.get(roomId);
        if (streamer.ws.readyState === WebSocket.OPEN) {
          streamer.ws.send(JSON.stringify({
            type: 'ice-candidate',
            data: data.data,
            from: clientId
          }));
        }
      }
    }
  }
  
  // 处理弹幕消息
  function handleDanmaku(data, roomId, clientId) {
    console.log('服务器收到弹幕消息:', data);
    
    // 处理两种可能的弹幕消息格式
    let danmakuData = data;
    if (data.data) {
      // 格式1: {type: 'danmaku', data: {...}, roomId: '...'}
      danmakuData = data.data;
    }
    
    console.log('处理后的弹幕数据:', danmakuData);
    
    // 转发弹幕给主播
    if (streamers.has(roomId)) {
      const streamer = streamers.get(roomId);
      if (streamer.ws.readyState === WebSocket.OPEN) {
        streamer.ws.send(JSON.stringify({
          type: 'danmaku',
          data: danmakuData,
          from: clientId
        }));
        console.log(`转发弹幕给主播: ${clientId} -> streamer`);
      }
    }
    
    // 广播给房间内其他观众
    if (rooms.has(roomId)) {
      const room = rooms.get(roomId);
      room.forEach((client, targetClientId) => {
        if (targetClientId !== clientId && client.type === 'viewer' && client.ws.readyState === WebSocket.OPEN) {
          client.ws.send(JSON.stringify({
            type: 'broadcast-danmaku',
            data: danmakuData,
            from: clientId
          }));
          console.log(`广播弹幕给观众: ${clientId} -> ${targetClientId}`);
        }
      });
    }
  }
  
  // 处理签到
  function handleCheckIn(ws, data, roomId, clientId) {
    if (!checkInData.has(roomId)) {
      checkInData.set(roomId, { count: 0, users: new Set() });
    }
    const roomStats = checkInData.get(roomId);

    if (roomStats.users.has(clientId)) {
      ws.send(JSON.stringify({
        type: 'error',
        data: {
          message: '您已签到过'
        }
      }));
      return;
    }

    roomStats.count++;
    roomStats.users.add(clientId);

    console.log(`签到: 房间 ${roomId}, 用户 ${clientId}, 当前签到数: ${roomStats.count}`);

    // 发送签到成功消息给签到用户
    ws.send(JSON.stringify({
      type: 'check-in-success',
      data: {
        roomId,
        clientId,
        count: roomStats.count
      }
    }));

    // 广播签到统计给房间内所有用户
    broadcastToRoom(roomId, {
      type: 'check-in-stats',
      roomId,
      count: roomStats.count,
      users: Array.from(roomStats.users)
    }, null); // 不排除任何用户，让所有人都收到更新
  }

  // 处理获取签到统计
  function handleGetCheckInStats(ws, roomId, clientId) {
    if (checkInData.has(roomId)) {
      const roomStats = checkInData.get(roomId);
      ws.send(JSON.stringify({
        type: 'check-in-stats',
        data: {
          roomId,
          count: roomStats.count,
          users: Array.from(roomStats.users)
        }
      }));
      console.log(`获取签到统计: 房间 ${roomId}, 用户 ${clientId}`);
    } else {
      ws.send(JSON.stringify({
        type: 'check-in-stats',
        data: {
          roomId,
          count: 0,
          users: []
        }
      }));
      console.log(`获取签到统计: 房间 ${roomId}, 用户 ${clientId} (无签到数据)`);
    }
  }

  // 处理重置签到
  function handleResetCheckIn(roomId, clientId) {
    if (checkInData.has(roomId)) {
      checkInData.get(roomId).count = 0;
      checkInData.get(roomId).users.clear();
      console.log(`重置签到: 房间 ${roomId}, 用户 ${clientId}`);
      
      // 广播重置消息给房间内所有用户
      broadcastToRoom(roomId, {
        type: 'check-in-reset',
        roomId,
        count: 0,
        users: []
      }, null);
    } else {
      console.log(`重置签到: 房间 ${roomId} 不存在`);
    }
  }
  
  // 处理聊天消息
  function handleChatMessage(data, roomId, clientId) {
    if (rooms.has(roomId)) {
      broadcastToRoom(roomId, {
        type: 'chat-message',
        userId: clientId,
        message: data.message,
        timestamp: new Date().toISOString()
      }, clientId);
    }
  }

  // 处理开始投票
  function handleStartVote(ws, data, roomId, clientId) {
    console.log(`尝试开始投票: 房间 ${roomId}, 用户 ${clientId}`);
    console.log(`当前主播信息:`, streamers.has(roomId) ? streamers.get(roomId) : '无主播');
    
    // 检查是否是主播
    if (!streamers.has(roomId)) {
      console.log(`房间 ${roomId} 没有主播`);
      ws.send(JSON.stringify({
        type: 'error',
        data: {
          message: '房间没有主播，请先开始直播'
        }
      }));
      return;
    }
    
    if (streamers.get(roomId).clientId !== clientId) {
      console.log(`用户 ${clientId} 不是主播，主播是 ${streamers.get(roomId).clientId}`);
      ws.send(JSON.stringify({
        type: 'error',
        data: {
          message: '只有主播可以开始投票'
        }
      }));
      return;
    }

    const { question, options } = data.data;
    
    // 初始化投票数据
    voteData.set(roomId, {
      isActive: true,
      question: question,
      options: options,
      results: {},
      totalVotes: 0,
      voters: new Set()
    });

    console.log(`开始投票: 房间 ${roomId}, 问题: ${question}, 选项: ${options.join(', ')}`);

    // 广播投票开始消息给所有观众
    broadcastToRoom(roomId, {
      type: 'vote-start',
      data: {
        question: question,
        options: options
      }
    }, null);
  }

  // 处理结束投票
  function handleEndVote(ws, roomId, clientId) {
    // 检查是否是主播
    if (!streamers.has(roomId) || streamers.get(roomId).clientId !== clientId) {
      ws.send(JSON.stringify({
        type: 'error',
        data: {
          message: '只有主播可以结束投票'
        }
      }));
      return;
    }

    if (!voteData.has(roomId) || !voteData.get(roomId).isActive) {
      ws.send(JSON.stringify({
        type: 'error',
        data: {
          message: '没有进行中的投票'
        }
      }));
      return;
    }

    const voteInfo = voteData.get(roomId);
    voteInfo.isActive = false;

    console.log(`结束投票: 房间 ${roomId}, 总票数: ${voteInfo.totalVotes}`);

    // 广播投票结束消息给所有观众
    broadcastToRoom(roomId, {
      type: 'vote-end',
      data: {
        results: voteInfo.results,
        totalVotes: voteInfo.totalVotes
      }
    }, null);
  }

  // 处理投票
  function handleVote(ws, data, roomId, clientId) {
    if (!voteData.has(roomId) || !voteData.get(roomId).isActive) {
      ws.send(JSON.stringify({
        type: 'vote-error',
        data: {
          message: '没有进行中的投票'
        }
      }));
      return;
    }

    const voteInfo = voteData.get(roomId);
    const { optionIndex } = data.data;

    // 检查是否已经投票
    if (voteInfo.voters.has(clientId)) {
      ws.send(JSON.stringify({
        type: 'vote-error',
        data: {
          message: '您已经投过票了'
        }
      }));
      return;
    }

    // 检查选项是否有效
    if (optionIndex < 0 || optionIndex >= voteInfo.options.length) {
      ws.send(JSON.stringify({
        type: 'vote-error',
        data: {
          message: '无效的投票选项'
        }
      }));
      return;
    }

    // 记录投票
    voteInfo.voters.add(clientId);
    voteInfo.results[optionIndex] = (voteInfo.results[optionIndex] || 0) + 1;
    voteInfo.totalVotes++;

    console.log(`投票: 房间 ${roomId}, 用户 ${clientId}, 选项 ${optionIndex}, 总票数: ${voteInfo.totalVotes}`);

    // 发送投票成功消息给投票者
    ws.send(JSON.stringify({
      type: 'vote-success',
      data: {
        selectedOption: optionIndex
      }
    }));

    // 广播投票更新消息给所有用户（包括主播）
    broadcastToRoom(roomId, {
      type: 'vote-update',
      data: {
        results: voteInfo.results,
        totalVotes: voteInfo.totalVotes,
        voters: Array.from(voteInfo.voters)
      }
    }, null);
  }

  // 处理重置投票
  function handleResetVote(roomId, clientId) {
    // 检查是否是主播
    if (!streamers.has(roomId) || streamers.get(roomId).clientId !== clientId) {
      return;
    }

    voteData.delete(roomId);
    console.log(`重置投票: 房间 ${roomId}`);

    // 广播投票重置消息给所有观众
    broadcastToRoom(roomId, {
      type: 'vote-reset',
      data: {}
    }, null);
  }

  // 处理获取投票统计
  function handleGetVoteStats(ws, roomId, clientId) {
    if (voteData.has(roomId)) {
      const voteInfo = voteData.get(roomId);
      ws.send(JSON.stringify({
        type: 'vote-stats',
        data: {
          isActive: voteInfo.isActive,
          question: voteInfo.question,
          options: voteInfo.options,
          results: voteInfo.results,
          totalVotes: voteInfo.totalVotes,
          voters: Array.from(voteInfo.voters)
        }
      }));
    } else {
      ws.send(JSON.stringify({
        type: 'vote-stats',
        data: {
          isActive: false,
          question: '',
          options: [],
          results: {},
          totalVotes: 0,
          voters: []
        }
      }));
    }
  }
  
  // 处理断开连接
  function handleDisconnection(roomId, clientId, wasStreamer) {
    if (rooms.has(roomId)) {
      const room = rooms.get(roomId);
      room.delete(clientId);
      
      if (wasStreamer) {
        // 主播断开，通知所有观众
        streamers.delete(roomId);
        broadcastToRoom(roomId, {
          type: 'stream-ended',
          message: '直播已结束'
        });
        console.log(`直播结束: 房间 ${roomId}`);
      } else {
        // 观众断开，通知主播
        if (streamers.has(roomId)) {
          const streamer = streamers.get(roomId);
          if (streamer.ws.readyState === WebSocket.OPEN) {
            streamer.ws.send(JSON.stringify({
              type: 'viewer-leave',
              from: clientId
            }));
          }
        }
      }
      
      // 如果房间空了，删除房间
      if (room.size === 0) {
        rooms.delete(roomId);
        console.log(`房间 ${roomId} 已清空`);
      }
    }
  }
});

// 向房间广播消息
function broadcastToRoom(roomId, message, excludeClientId = null) {
  if (rooms.has(roomId)) {
    const room = rooms.get(roomId);
    room.forEach((client, clientId) => {
      if (clientId !== excludeClientId && client.ws.readyState === WebSocket.OPEN) {
        // 直接发送消息，不包装在data字段中
        client.ws.send(JSON.stringify(message));
      }
    });
  }
  
  // 同时发送给主播
  if (streamers.has(roomId)) {
    const streamer = streamers.get(roomId);
    if (streamer.ws.readyState === WebSocket.OPEN) {
      // 直接发送消息，不包装在data字段中
      streamer.ws.send(JSON.stringify(message));
    }
  }
}

// 生成客户端ID
function generateClientId() {
  return 'client_' + Math.random().toString(36).substr(2, 9);
}

// 监听端口
server.listen(9000, '0.0.0.0', () => {
  console.log('WebRTC信令服务器运行在端口 9000');
  console.log('服务器地址: 0.0.0.0:9000');
  console.log('外部访问地址: http://192.168.8.41:9000');
});